%%%-------------------------------------------------------------------
%%% File	: soap_registry_server.erl
%%% Author	: Anton Fedorov <datacompboy@call2ru.com>
%%% Original Author : Erik Reitsma <elnerei@tina29.etm.ericsson.se>
%%% Description : Server for SOAP XSDs
%%%
%%% Created :  8 Dec 2003 by Erik Reitsma <elnerei@tina29.etm.ericsson.se>
%%% Updated : 18 sep 2006 by Anton Fedorov <datacompboy@call2ru.com>
%%%-------------------------------------------------------------------
-module(soap_registry_server).
-vsn("0.4").

-behaviour(gen_server).
%%--------------------------------------------------------------------
%% Include files
%%--------------------------------------------------------------------

%%--------------------------------------------------------------------
%% External exports
-export([start_link/1,start/1,start_link/0,start/0,stop/0]).
-export([add_xsd/2,get_xsd/1]).

%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).

-record(state, {envmodel,xsdlist}).

-define(SERVER,?MODULE).

%%====================================================================
%% External functions
%%====================================================================

%%--------------------------------------------------------------------
%% Function: start_link/0
%% Description: Starts the server with "soap-envelope.xsd" as envelope model
%%--------------------------------------------------------------------
start_link() ->
	EnvelopeFile = case application:get_env(erlsoap,soap_envelope_xsd) of
		{ok,EnvFile} -> EnvFile;
		undefined -> "soap-envelope.xsd"
	end,
	start_link(EnvelopeFile).

%%--------------------------------------------------------------------
%% Function: start_link/1
%% Description: Starts the server with given file as envelope model
%%--------------------------------------------------------------------
start_link(EnvModel) ->
	gen_server:start_link({local, ?SERVER}, ?MODULE, [EnvModel], []).

%%--------------------------------------------------------------------
%% Function: start/0
%% Description: Starts the server with "soap-envelope.xsd" as envelope model
%%--------------------------------------------------------------------
start() ->
	EnvelopeFile = case application:get_env(erlsoap,soap_envelope_xsd) of
		{ok,EnvFile} -> EnvFile;
		undefined -> "soap-envelope.xsd"
	end,
	start(EnvelopeFile).

%%--------------------------------------------------------------------
%% Function: start/1
%% Description: Starts the server with given file as envelope model
%%--------------------------------------------------------------------
start(EnvModel) ->
	gen_server:start({local, ?SERVER}, ?MODULE, [EnvModel], []).

%%====================================================================
%% Server functions
%%====================================================================

add_xsd(URL,XSDFile) ->
	gen_server:call(?SERVER,{add_xsd,URL,XSDFile}).

get_xsd(URL) ->
	gen_server:call(?SERVER,{get_xsd,URL}).

stop() ->
	gen_server:cast(?SERVER,stop).

%%--------------------------------------------------------------------
%% Function: init/1
%% Description: Initiates the server
%% Returns: {ok, State} 		 |
%%			{ok, State, Timeout} |
%%			ignore				 |
%%			{stop, Reason}
%%--------------------------------------------------------------------
init([EnvelopeFile]) ->
	{ok, EnvModel} = erlsom:compile_file(EnvelopeFile,"soap"),
	{ok, #state{envmodel = EnvModel, xsdlist=ets:new(operation_table,[])}}.

%%--------------------------------------------------------------------
%% Function: handle_call/3
%% Description: Handling call messages
%% Returns: {reply, Reply, State}		   |
%%			{reply, Reply, State, Timeout} |
%%			{noreply, State}			   |
%%			{noreply, State, Timeout}	   |
%%			{stop, Reason, Reply, State}   | (terminate/2 is called)
%%			{stop, Reason, State}			 (terminate/2 is called)
%%--------------------------------------------------------------------
handle_call({add_xsd,URL,XSDFile}, _From, State) ->
	case (catch erlsom:add_file(XSDFile,"p",State#state.envmodel)) of
		{'EXIT', Reason} -> {reply, {error, Reason}, State};
		Model -> ets:insert(State#state.xsdlist,{URL,Model}),
				{reply,ok,State}
	end;

handle_call({get_xsd,URL}, _From, State) ->
	case ets:lookup(State#state.xsdlist,URL) of
	[] ->
		{reply,{error,not_found},State};
	[{URL,Model}] ->
		{reply,{ok,Model},State}
	end;

handle_call(_Call, _From, State) ->
	{reply, {error,not_implemented}, State}.

%%--------------------------------------------------------------------
%% Function: handle_cast/2
%% Description: Handling cast messages
%% Returns: {noreply, State}		  |
%%			{noreply, State, Timeout} |
%%			{stop, Reason, State}			 (terminate/2 is called)
%%--------------------------------------------------------------------
handle_cast(stop, State) ->
	{stop, normal, State};

handle_cast(_Msg, State) ->
	{noreply, State}.

%%--------------------------------------------------------------------
%% Function: handle_info/2
%% Description: Handling all non call/cast messages
%% Returns: {noreply, State}		  |
%%			{noreply, State, Timeout} |
%%			{stop, Reason, State}			 (terminate/2 is called)
%%--------------------------------------------------------------------
handle_info(_Info, State) ->
	{noreply, State}.

%%--------------------------------------------------------------------
%% Function: terminate/2
%% Description: Shutdown the server
%% Returns: any (ignored by gen_server)
%%--------------------------------------------------------------------
terminate(_Reason, State) ->
	ets:delete(State#state.xsdlist),
	ok.

%%--------------------------------------------------------------------
%% Func: code_change/3
%% Purpose: Convert process state when code is changed
%% Returns: {ok, NewState}
%%--------------------------------------------------------------------
code_change(_OldVsn, State, _Extra) ->
	{ok, State}.

%%--------------------------------------------------------------------
%% Internal functions
%%--------------------------------------------------------------------
